/**
 *  TinyPasswordManager
 *  Copyright (C) 2008 Gross David <gdavid.devel@gmail.com>
 *                     Vinet Guillaume <vinet.guillaume@gmail.com>
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/


#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "ui_about.h"
#include "exceptions.h"
#include "sha256.h"

// TODO : => LINUX too !
#ifdef WIN32
#include "firefoxpasswordmanager.h"
#include "firefoxpassworddialog.h"
#endif

#include <QtCore/QFile>
#include <QtGui/QClipboard>
#include <QtCore/QTimer>
#include <QtGui/QFileDialog>
#include <QtGui/QKeyEvent>
#include <QMessageBox>
#include <QTranslator>
#include <QToolTip>

#include <vector>
#include <string>
#include <cmath>

//
// Public
//

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent), m_tpm(new TinyPasswordManager), m_ui(new Ui::MainWindow),
      m_dbState(NONE), m_submitAction(NOACTION), m_passwordTimer(new QTimer(this)), 
      m_clipboardTimer(new QTimer(this)), m_translator(new QTranslator(NULL)) {
    m_ui->setupUi(this);
    
    setWindowTitle("TinyPasswordManager");
    setIcons();
    
    createSystrayIcon();
    createConnections();
    init();
}

MainWindow::~MainWindow() {
    delete m_tpm;
    SHA256::kill();
    delete m_ui;
}

//
// Protected
//

void MainWindow::keyPressEvent(QKeyEvent * event) {
    if (event->key() == Qt::Key_Return) {
        if (m_ui->editKey->hasFocus())
            m_ui->buttonDecipher->click();
    }
}

void MainWindow::closeEvent(QCloseEvent *event) {
    hide();
    event->ignore();
}

//
// Private
//

void MainWindow::setIcons() {
    m_ui->actionLoad->setIcon(QIcon(":images/open"));
    m_ui->actionQuit->setIcon(QIcon("images/exit"));

    m_ui->buttonAdd->setIcon(QIcon(":images/add"));
    m_ui->buttonDel->setIcon(QIcon(":images/delete"));
    m_ui->buttonShowPasswords->setIcon(QIcon(":images/password"));
    m_ui->buttonEdit->setIcon(QIcon(":images/edit"));
    m_ui->buttonGenerate->setIcon(QIcon(":images/generate"));
    m_ui->buttonSubmit->setIcon(QIcon(":images/submit"));
    m_ui->buttonShowPassword->setIcon(QIcon(":images/see"));
    
    m_ui->actionFrench->setIcon(QIcon(":images/fr"));
    m_ui->actionEnglish->setIcon(QIcon(":images/uk"));
}

void MainWindow::createConnections() {
    connect(m_ui->buttonAdd, SIGNAL(clicked()), this, SLOT(addIdentifier()));
    connect(m_ui->buttonEdit, SIGNAL(clicked()), this, SLOT(editIdentifier()));
    connect(m_ui->buttonDel, SIGNAL(clicked()), this, SLOT(removeIdentifier()));
    connect(m_ui->buttonShowPasswords, SIGNAL(toggled(bool)), this, SLOT(showPasswords(bool)));
    connect(m_ui->buttonDecipher, SIGNAL(clicked()), this, SLOT(dbAction()));
    connect(m_ui->editPassword, SIGNAL(textChanged(const QString &)), this, SLOT(mesurePasswordQuality(const QString &)));
    connect(m_ui->buttonSubmit, SIGNAL(clicked()), this, SLOT(saveIdentifier()));
    connect(m_ui->buttonGenerate, SIGNAL(clicked()), this, SLOT(generatePassword()));
    connect(m_ui->buttonShowPassword, SIGNAL(toggled(bool)), this, SLOT(showClearPassword(bool)));
	connect(m_ui->editKey, SIGNAL(textChanged(const QString &)), this, SLOT(enableDecipherButton(const QString &)));
	connect(m_ui->editDesc, SIGNAL(textChanged(const QString &)), this, SLOT(enableSubmitButton()));
	connect(m_ui->editLogin, SIGNAL(textChanged(const QString &)), this, SLOT(enableSubmitButton()));
	connect(m_ui->editPassword, SIGNAL(textChanged(const QString &)), this, SLOT(enableSubmitButton()));

    connect(m_ui->tableIdents, SIGNAL(copyPassword()), this, SLOT(copyPassword()));
    connect(m_ui->tableIdents, SIGNAL(edit()), this, SLOT(editIdentifier()));
    connect(m_ui->tableIdents, SIGNAL(remove()), this, SLOT(removeIdentifier()));
    connect(m_ui->tableIdents, SIGNAL(keyEvent(QKeyEvent *)), this, SLOT(keyEventIdentifier(QKeyEvent *)));

    connect(m_ui->actionLoad, SIGNAL(triggered()), this, SLOT(openDbFrom()));

// TODO : => LINUX too !
#ifdef WIN32
    connect(m_ui->actionImport, SIGNAL(triggered()), this, SLOT(importFromFirefox()));
#endif

    connect(m_ui->actionFrench, SIGNAL(triggered()), this, SLOT(translateToFrench()));
    connect(m_ui->actionEnglish, SIGNAL(triggered()), this, SLOT(translateToEnglish()));
    connect(m_ui->actionQuit, SIGNAL(triggered()), this, SLOT(quit()));
    connect(m_ui->actionAbout, SIGNAL(triggered()), this, SLOT(about()));

    connect(m_passwordTimer, SIGNAL(timeout()), this, SLOT(autoHidePassword()));
    connect(m_clipboardTimer, SIGNAL(timeout()), this, SLOT(clearClipboard()));
    
    connect(m_trayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), 
            this, SLOT(systrayActivated(QSystemTrayIcon::ActivationReason)));

    connect(m_quitAction, SIGNAL(triggered()), qApp, SLOT(quit()));
}

void MainWindow::createSystrayIcon() {
    m_trayIconMenu = new QMenu(this);
    m_quitAction = new QAction(tr("&Quit"), this);
    m_trayIconMenu->addAction(m_quitAction);

    m_trayIcon = new QSystemTrayIcon(this);
    m_trayIcon->setContextMenu(m_trayIconMenu);
    m_trayIcon->setIcon(QIcon(":images/tpm"));
    m_trayIcon->show();
}

void MainWindow::init() {
    m_ui->tableIdents->setSelectionMode(QAbstractItemView::SingleSelection);
    m_ui->tableIdents->setSelectionBehavior(QAbstractItemView::SelectRows);
    m_ui->tableIdents->setEditTriggers(QAbstractItemView::NoEditTriggers);
    m_ui->tableIdents->setAlternatingRowColors(true);
    m_ui->tableIdents->setShowGrid(false);
    m_ui->tableIdents->hideColumn(2);

    m_ui->groupEditor->setVisible(false);

    m_ui->buttonAdd->setEnabled(false);
    m_ui->buttonEdit->setEnabled(false);
    m_ui->buttonDel->setEnabled(false);
    m_ui->actionImport->setEnabled(false);

    dbAction();

    m_passwordTimer->setSingleShot(true);
    m_clipboardTimer->setSingleShot(true);
}

void MainWindow::statusMsg(MsgType type, const QString &msg) {
    if(type == MSG_INFO)
        statusBar()->setStyleSheet("color:green; font:bold;");
    else if(type == MSG_ERROR)
        statusBar()->setStyleSheet("color:red; font:bold;");
    else
        statusBar()->setStyleSheet("");

    statusBar()->showMessage(msg, 10000);
}

void MainWindow::setErrorStyle(QWidget *widget, bool invalid) {
    if (invalid)
        widget->setStyleSheet("border-color: red;");
    else
        widget->setStyleSheet("");
}

//
// Public slots
//

void MainWindow::showEditor(bool visible) {
    m_ui->groupEditor->setVisible(visible);
    m_ui->groupDatabase->setEnabled(!visible);
}

bool MainWindow::editorIsOpen() {
    return m_ui->groupEditor->isVisible();
}

void MainWindow::showPasswords(bool visible) {
    if (visible)
        m_ui->tableIdents->showColumn(2);
    else
        m_ui->tableIdents->hideColumn(2);
}

void MainWindow::showClearPassword(bool visible) {
    if (visible)
        m_ui->editPassword->setEchoMode(QLineEdit::Normal);
    else
        m_ui->editPassword->setEchoMode(QLineEdit::Password);
}

void MainWindow::generatePassword() {
    std::string charset("azertyuiopqsdfghjklmwxcvbn&~'{}@-_()%!?/\\^$*+[]:.;,0123456789AZERTYUIOPQSDFGHJKLMWXCVBN");
    std::string password = TinyPasswordManager::generatePassword(15, 20, charset);

    m_ui->buttonShowPassword->setChecked(true);
    showClearPassword(true);
    m_passwordTimer->start(1000);
    m_ui->editPassword->setText(QString::fromStdString(password));
}

void MainWindow::openDb(const QString &path) {
    try {
        if(path.isEmpty())
            m_tpm->openDatabase();
        else
            m_tpm->openDatabase(path.toStdString());

        m_ui->buttonDecipher->setIcon(QIcon(":images/decrypt"));
        m_ui->buttonDecipher->setText(tr("Decipher"));
        m_dbState = OPENED;
        statusMsg(MSG_INFO, tr("Database successfully opened"));
    }
    catch(ExFileNotFound &) {
        m_ui->buttonDecipher->setIcon(QIcon(":/images/encrypt"));
        m_ui->buttonDecipher->setText(tr("Create a database"));
        m_dbState = NEW;
        statusMsg(MSG_INFO, tr("No existing database found"));
    }
    catch(std::exception &ex) {
        statusMsg(MSG_ERROR, QString::fromStdString(ex.what()));
    }

    m_ui->editKey->setFocus();
}

void MainWindow::openDbFrom() {
#ifdef WIN32
	QString defaultDirectory("C:\\"); 
#else
	QString defaultDirectory("~/"); 
#endif
	
    QString fileName = QFileDialog::getOpenFileName(this, tr("Open Database"),
                                                    defaultDirectory,
                                                    tr("tpm database file (*.db)"));
    openDb(fileName);
}

// TODO : => LINUX too !
#ifdef WIN32
void MainWindow::importFromFirefox() {
#ifdef WIN32
    QFileInfo appFirefox("C:\\Program Files\\Mozilla Firefox\\firefox.exe");
	QString dirFirefox("C:\\Program Files\\Mozilla Firefox\\");
	
    if(!appFirefox.exists())
        dirFirefox = QFileDialog::getExistingDirectory(this, tr("Select the installation directory of Firefox"),
                                                       "C:\\Program Files\\",
                                                       QFileDialog::ShowDirsOnly);

    FirefoxPasswordManager firefoxPM(dirFirefox.toStdString());
#else
    FirefoxPasswordManager firefoxPM();
#endif

    std::vector<Identifier *> idents;

    try {
        firefoxPM.init();
		
        if(!firefoxPM.checkUserPassword("")) {
            FirefoxPasswordDialog *dialog = new FirefoxPasswordDialog(this);
            int res = dialog->exec();
            std::string password = dialog->getMasterPassword();
                
            if(res == QDialog::Accepted &&
               !firefoxPM.checkUserPassword(password)) {
                QMessageBox::warning(this, tr("Error"), tr("Wrong Firefox master password"));
                firefoxPM.terminate();
                return;
            }
            else if(res == QDialog::Rejected) {
                firefoxPM.terminate();
                return;
            }
        }
            
        firefoxPM.getCredentials(idents);
        firefoxPM.terminate();
	}
    catch(std::exception &ex) {
        QMessageBox::warning(this, tr("Error"), ex.what());
    }
    
    try {
        for(std::vector<Identifier *>::const_iterator it = idents.begin(); it != idents.end(); ++it) {
            m_tpm->addIdentifier(*(*it));
            delete (*it);
        }
        
        m_tpm->save();
        reloadTableContent();
    }
    catch(std::exception &ex) {
        QMessageBox::critical(this, tr("Error"), ex.what());
    }
}
#endif

void MainWindow::loadDb() {
    unsigned char digestKey[32]; memset(digestKey, 0, 32);

    std::string key = m_ui->editKey->text().toStdString();
    SHA256::getInstance()->digest(key, digestKey);

    m_tpm->setPrivateKey(digestKey);

    memset(digestKey, 0, 32);

    try {
        if(!m_tpm->isBeingUsed()) {
            m_tpm->createEmptyDatabase("tpm.db");
            m_dbState = LOADED;
            statusMsg(MSG_INFO, tr("Database successfully created"));
        }
        else {
            m_tpm->getIdentifiers();
            reloadTableContent();
        
            m_dbState = LOADED;
            statusMsg(MSG_INFO, tr("Database successfully loaded"));
            
            m_ui->tableIdents->setFocus();

            if(m_ui->tableIdents->rowCount() > 0)
                m_ui->tableIdents->selectRow(0);
        } 
   
        m_ui->editKey->clear();
        m_ui->buttonAdd->setEnabled(true);
        m_ui->buttonEdit->setEnabled(true);
        m_ui->buttonDel->setEnabled(true);

// TODO : => LINUX too !
#ifdef WIN32
        m_ui->actionImport->setEnabled(true);
#endif

        m_ui->buttonDecipher->setText(tr("Change private key"));
    }
    catch(std::exception &ex) {
        statusMsg(MSG_ERROR, QString::fromStdString(ex.what()));
        m_ui->editKey->setFocus();
    }
}

void MainWindow::changePrivateKey() {
    if(m_ui->editKey->text().size() == 0) {
        statusMsg(MSG_ERROR, tr("Can't use empty private key"));
        m_ui->editKey->setFocus();
    }
    else {    
        QMessageBox msgBox;
        msgBox.setIcon(QMessageBox::Warning);
        msgBox.setText(tr("The private key of the database is going to be changed."));
        msgBox.setInformativeText(tr("Are you sure you want to changed the AES private key ?"));
        msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
        msgBox.setDefaultButton(QMessageBox::No);
        int ret = msgBox.exec();

        if(ret == QMessageBox::Yes) {
            unsigned char digestKey[32]; memset(digestKey, 0, 32);

            std::string key = m_ui->editKey->text().toStdString();
            SHA256::getInstance()->digest(key, digestKey);

            m_tpm->setPrivateKey(digestKey);
            m_tpm->save();

            m_ui->editKey->clear();
        }
    }
}

void MainWindow::reloadTableContent() {
    m_ui->tableIdents->clearContents();
    m_ui->tableIdents->setRowCount(0);
    Identifier ident;
    
    for(unsigned int i = 0; i < m_tpm->size(); ++i) {
        ident = m_tpm->at(i);
        m_ui->tableIdents->addIdentifier(ident);
    }
}

void MainWindow::copyPassword() {
    int currentRow = m_ui->tableIdents->currentRow();
    
    if(currentRow >= 0) {
        Identifier id = m_ui->tableIdents->getIdentifier(currentRow);
        QApplication::clipboard()->setText(QString::fromStdString(id.getPassword()));
    }

    m_clipboardTimer->start(10000);
}

void MainWindow::resetEditorFields() {
    m_ui->editLogin->clear();
    setErrorStyle(m_ui->editLogin, false);
    m_ui->editPassword->clear();
    setErrorStyle(m_ui->editPassword, false);
    m_ui->editDesc->clear();
    setErrorStyle(m_ui->editDesc, false);
}

void MainWindow::quit() {
    QApplication::quit();
}

//
// Private slots
//

void MainWindow::about() {
    Ui::About *uiAbout = new Ui::About;
    QDialog *dialogAbout = new QDialog(this);
    uiAbout->setupUi(dialogAbout);
	uiAbout->textAbout->setText(tr("TinyPasswordManager is an application that allows you to manage all of your accounts. Written in C++, TinyPasswordManager is using AES-256 to cipher the database. The AES private key is the result of the SHA-256  function of your password.\n\
\n\
Authors :\n\
- Gross David <gdavid.devel@gmail.com>\n\
- Guillaume Vinet <guillaume.vinet@gmail.com>\n\
\n\
Code License : GNU GPLv3\n\
\n\
Homepage : http://code.google.com/p/tinypasswordmanager"));
    dialogAbout->setWindowTitle(tr("About"));
    dialogAbout->show();
}

void MainWindow::autoHidePassword() {
    showClearPassword(false);
    m_ui->buttonShowPassword->setChecked(false);
}

void MainWindow::clearClipboard() {
    QApplication::clipboard()->clear();
}

void MainWindow::dbAction() {
    switch(m_dbState) {
        case NONE:
        {
            QString defaultPath = QCoreApplication::applicationDirPath() + "/tpm.db";
            openDb(defaultPath);
        }
            break;
        case NEW:
        case OPENED:
            loadDb();
            break;
        case LOADED:
            changePrivateKey();
            break;
    }
}

void MainWindow::addIdentifier() {
    showEditor(true); 
    m_submitAction = SAVE;
    m_ui->editDesc->setFocus();
}

void MainWindow::editIdentifier() {
    int currentRow = m_ui->tableIdents->currentRow();
    if(currentRow < 0)
        statusMsg(MSG_ERROR, tr("Select an entry to edit"));
    else {
        Identifier id = m_ui->tableIdents->getIdentifier(currentRow);
        m_ui->editDesc->setText(QString::fromStdString(id.getDescription()));
        m_ui->editLogin->setText(QString::fromStdString(id.getLogin()));
        m_ui->editPassword->setText(QString::fromStdString(id.getPassword()));
        m_ui->buttonShowPassword->setChecked(false);
        
        m_ui->tableIdents->removeIdentifier(currentRow);
        m_tpm->removeIdentifier(id);
        
        showClearPassword(false);
        showEditor(true);
        m_submitAction = EDIT;
        m_ui->editDesc->setFocus();
    }
}

void MainWindow::saveIdentifier() {
    QString login = m_ui->editLogin->text();
    QString pass = m_ui->editPassword->text();
    QString descr = m_ui->editDesc->text();
    bool editorValid = (!login.isEmpty() && !pass.isEmpty()
                        && !descr.isEmpty() && m_submitAction != NOACTION);

    if(editorValid) {
        try {
            Identifier ident(login.toStdString(), pass.toStdString(), descr.toStdString());
            m_tpm->addIdentifier(ident);
            m_tpm->save();
            
            if(m_submitAction == SAVE)
                statusMsg(MSG_INFO, tr("Identifier successfully added to the database"));
            else if(m_submitAction == EDIT)
                statusMsg(MSG_INFO, tr("Identifier successfully edited"));

            reloadTableContent();
            resetEditorFields();
            showEditor(false);
            m_submitAction = NOACTION;
        }
        catch(std::exception &ex) {
            statusMsg(MSG_ERROR, QString::fromStdString(ex.what()));
        }
    }
    else {
        if (m_submitAction == NOACTION)
            statusMsg(MSG_ERROR, tr("Internal MSG_ERROR, no action given to submiting"));
        else {
            if(login.isEmpty())
                setErrorStyle(m_ui->editLogin, true);
            if(pass.isEmpty())
                setErrorStyle(m_ui->editPassword, true);
            if(descr.isEmpty())
                setErrorStyle(m_ui->editDesc, true);
            statusMsg(MSG_ERROR, tr("Invalid content"));
        }
    }
}

void MainWindow::removeIdentifier() {
    int currentRow = m_ui->tableIdents->currentRow();
    
    if(currentRow < 0)
        statusMsg(MSG_ERROR, tr("Select an entry to edit"));
    else {
        QMessageBox msgBox;
        msgBox.setIcon(QMessageBox::Warning);
        msgBox.setText(tr("An identifier of the database is going to be removed."));
        msgBox.setInformativeText(tr("Are you sure you want to remove this identifier ?"));
        msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
        msgBox.setDefaultButton(QMessageBox::No);
        int ret = msgBox.exec();

        if(ret == QMessageBox::Yes) {
            Identifier id = m_ui->tableIdents->getIdentifier(currentRow);
            m_ui->tableIdents->removeIdentifier(currentRow);
            m_tpm->removeIdentifier(id);
            m_tpm->save();
        }
    }
}

void MainWindow::keyEventIdentifier(QKeyEvent *event) {
    int key = event->key();
   
    if(key == Qt::Key_Delete)
        removeIdentifier();
    else if(event->matches(QKeySequence::Copy))
        copyPassword();
    else if(key >= Qt::Key_A && key <= Qt::Key_Z) {
        Identifier ident;
        unsigned int i;

        for(i = 0; i < m_tpm->size(); ++i) {
            ident = m_tpm->at(i);
            char firstLetter = ident.getDescription().at(0);
			
            if(firstLetter >= 0x61 && firstLetter <= 0x7A && firstLetter >= (key + 0x20))
                break;
            else if(firstLetter >= 0x41 && firstLetter <= 0x5A && firstLetter >= key)
                break;
        }

        if(i == m_tpm->size())
            --i;

        m_ui->tableIdents->setCurrentCell(i, 0);
    }
    else if(key == Qt::Key_Up) {
        unsigned int currentRow = m_ui->tableIdents->currentRow();

        if(currentRow > 0)
            m_ui->tableIdents->setCurrentCell(currentRow - 1, 0);
    }
    else if(key == Qt::Key_Down) {
        unsigned int currentRow = m_ui->tableIdents->currentRow();

        if(currentRow < m_tpm->size() - 1)
            m_ui->tableIdents->setCurrentCell(currentRow + 1, 0);
    }
}

void MainWindow::enableSubmitButton() {
	bool disable = m_ui->editDesc->text().isEmpty();
	disable |= m_ui->editLogin->text().isEmpty();
	disable |= m_ui->editPassword->text().isEmpty();
	m_ui->buttonSubmit->setEnabled(!disable);
}

void MainWindow::enableDecipherButton(const QString &key) {
	m_ui->buttonDecipher->setEnabled(!key.isEmpty());
}

void MainWindow::mesurePasswordQuality(const QString &password) {
    if(password.isEmpty()) {
        m_ui->progressQuality->setFormat("Weak");
        m_ui->progressQuality->setValue(0);
        return;
    }
    
    QPalette pal = m_ui->progressQuality->palette();
    
    QByteArray charset;
    
    for(unsigned int i = 0; i < static_cast<unsigned int>(password.size()); ++i) {
        QChar currentChar = password.at(i);
        
        if(currentChar.isLower() && !charset.contains(currentChar.toAscii()))
            charset.append("abcdefghijklmnopqrstuvwxyz");
        else if(currentChar.isUpper() && !charset.contains(currentChar.toAscii()))
            charset.append("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
        else if(currentChar.isNumber() && !charset.contains(currentChar.toAscii()))
            charset.append("0123456789");
        else
            charset.append(QString(currentChar.toAscii()).append("     "));
    }
    
    double combinations = pow((double)charset.size(), (double)password.size());
    
    /*
     * The following step need some explanation.
     * 200,000,000 is the current number of computations of MD5 hash 
     * per second on a workstation. 
     * Why MD5 ? Because it is, at this time, the general hash function.
     * The quality of password will be judge with the time needed by an attacker
     * to break it.
     */
    double hours = combinations / ((double)200000000 * (double)3600);
    unsigned int quality;
    unsigned int value;
    QString format;
    
    if(hours < 1.0E+2) 
        quality = WEAK1;
    else if(hours < 1.0E+4) 
        quality = WEAK2;
    else if(hours < 1.0E+6) 
        quality = WEAK3;
    else if(hours < 1.0E+9) 
        quality = MEDIUM1;
    else if(hours < 1.0E+12) 
        quality = MEDIUM2;
    else if(hours < 1.0E+15) 
        quality = MEDIUM3;
    else if(hours < 1.0E+18) 
        quality = STRONG1;
    else if(hours < 1.0E+21) 
        quality = STRONG2;
    else
        quality = STRONG3;
    
    switch(quality) {
        case WEAK1:
            value = 11;
            format = tr("Weak");
            break;
        case WEAK2:
            value = 22;
            format = tr("Weak");
            break;
        case WEAK3:
            value = 33;
            format = tr("Weak");
            break;
        case MEDIUM1:
            value = 44;
            format = tr("Medium");
            break;
        case MEDIUM2:
            value = 55;
            format = tr("Medium");
            break;
        case MEDIUM3:
            value = 66;
            format = tr("Medium");
            break;
        case STRONG1:
            value = 77;
            format = tr("Strong");
            break;
        case STRONG2:
            value = 88;
            format = tr("Strong");
            break;
        case STRONG3:
            value = 100;
            format = tr("Strong");
            break;
    }

    m_ui->progressQuality->setFormat(format);
    m_ui->progressQuality->setValue(value);
}

void MainWindow::translateToFrench() {
    translate("fr");
}

void MainWindow::translateToEnglish() {
    translate("uk");
}

void MainWindow::translate(const QString &language) {
    if(language == "fr") {
        m_ui->actionFrench->setChecked(true);
        m_ui->actionEnglish->setChecked(false);
        m_ui->tableIdents->translate("fr");
    }
    else {
        m_ui->actionFrench->setChecked(false);
        m_ui->actionEnglish->setChecked(true);
        m_ui->tableIdents->translate("uk");
    }
    
    if(m_translator)
        qApp->removeTranslator(m_translator);
        
    if(language != "uk") {
        m_translator->load("i18n_" + language + ".qm", ":/translations/");
        qApp->installTranslator(m_translator);
    }
    
    m_ui->labelKey->setText(tr("Private key")); 
    m_ui->groupKey->setTitle(tr("Database access"));

    switch(m_dbState) {
		default:
        case NEW:
            m_ui->buttonDecipher->setText(tr("Create a database"));
            break;
        case OPENED:
            m_ui->buttonDecipher->setText(tr("Decipher"));
            break;
        case LOADED:
            m_ui->buttonDecipher->setText(tr("Change private key"));
            break;
    }
	   
    m_ui->groupDatabase->setTitle(tr("Database"));
    m_ui->groupEditor->setTitle(tr("Identifier"));
    m_ui->labelDescription->setText(tr("Description"));
    m_ui->labelLogin->setText(tr("Login"));
    m_ui->labelPassword->setText(tr("Password"));
    m_ui->labelQuality->setText(tr("Password quality"));
    m_ui->buttonSubmit->setText(tr("Submit"));
    m_ui->actionLoad->setText(tr("Load"));
    m_ui->actionImport->setText(tr("Import from Firefox"));
    m_ui->actionQuit->setText(tr("Quit"));
    m_ui->actionFrench->setText(tr("French"));
    m_ui->actionEnglish->setText(tr("English"));
    m_ui->actionAbout->setText(tr("About"));
    m_ui->actionPreferences->setText(tr("Preferences"));
    m_ui->menuFile->setTitle(tr("File"));
    m_ui->menuEdit->setTitle(tr("Edit"));
    m_ui->menuAbout->setTitle(tr("About"));
    m_ui->buttonGenerate->setToolTip(tr("Generate a pseudo-random password"));
    m_ui->buttonShowPassword->setToolTip(tr("Show the current password"));
    m_ui->buttonAdd->setToolTip(tr("Add an identifier to the database"));
    m_ui->buttonEdit->setToolTip(tr("Edit the selected identifier"));
    m_ui->buttonDel->setToolTip(tr("Remove an identifier from the database"));
    m_ui->buttonShowPasswords->setToolTip(tr("Show all passwords"));
    
    
    unsigned int value = m_ui->progressQuality->value();
    
    if(value < 44) 
        m_ui->progressQuality->setFormat(tr("Weak"));
    else if(value < 66)
        m_ui->progressQuality->setFormat(tr("Medium"));
    else
        m_ui->progressQuality->setFormat(tr("Strong"));
}

void MainWindow::systrayActivated(QSystemTrayIcon::ActivationReason reason) {
    switch (reason) {
        case QSystemTrayIcon::Trigger:
            if(isVisible())
                hide();
            else
                show();
                activateWindow();
        break;
        default:
            ;
    }
}

